home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / Ham⁄GPS / SoftKiss.src.1.8 Folder / SoftKiss.src.1.8 / core / sfk_core_command.c < prev    next >
Text File  |  1993-03-18  |  20KB  |  898 lines

  1.  /*
  2.  * SoftKiss command parser
  3.  * by Aaron Wohl / N3LIW (aw0g+@andrew.cmu.edu) jul 1990
  4.  * 6393 Penn Ave #303
  5.  * Pittsburgh PA, 15206
  6.  * work: (412)-268-5032
  7.  * home: (412)-731-6159
  8.  */
  9.  
  10. #define sfk_CORE_EXTERN
  11. #include "sfk_core.h"
  12. #include "sfk_core_private.h"
  13. #include <ctype.h>
  14.  
  15. /*
  16.  * define type of argument various commands can take
  17.  */
  18. #define SFK_CF_NO_ARG    (0)
  19. #define SFK_CF_BOOL     (1)
  20. #define SFK_CF_INT         (2)
  21. #define SFK_CF_TEXT     (3)
  22. #define SFK_CF_ARG_MASK (3)
  23.  
  24. #define SFK_CF_IMMEDIATE  (8)        /*can do this command while online*/
  25. #define SFK_CF_RO         (16)        /*readonly variables*/
  26. #define SFK_CF_HEX         (32)        /*print value in hex*/
  27.  
  28. #define sfk_BE_not_found 0
  29. #define sfk_BE_ambigous  1
  30. #define sfk_BE_found     2
  31.  
  32. #define FAKE_EOL_CH    (';')
  33.  
  34. #define SFK_TEXT_RESID (1024)
  35. #define SFK_COMMAND_RESID (1025)
  36.  
  37. /*
  38.  * information about each command, shared amongst all ports
  39.  */
  40. struct sfk_name_R {
  41.     char *nm_text;        /*text of the command*/
  42.     char *nm_help;        /*help message for command*/
  43.     char *nm_default;     /*default setting*/
  44.     int32 nm_flags;        /*what kind of command it is*/
  45.     int16 nm_val_num;    /*index into value table*/
  46. };
  47. typedef struct sfk_name_R sfk_name,*sfk_name_pt;
  48.  
  49. /*
  50.  * globals for parseing commands
  51.  */
  52. static struct {
  53.     sfk_name sfk_cmd_table[sfk_max_cmd_num];
  54.     /*allcate text variables in here*/
  55.     char string_space[SFK_NUM_TEXT*sfk_NUM_PORTS*sfk_STRING_SIZE];
  56.     char *string_allocator;
  57.     int sfk_cmd_table_size;
  58. }sfk_cgl;
  59.  
  60. /*
  61.  * fatal error
  62.  */
  63. void sfk_assert_fail(char *msg)
  64. {
  65.     unsigned char buf[256];
  66.     unsigned short len=strlen(msg);
  67.     len&=0xFF;
  68.     buf[0]=len;
  69.     memcpy(buf+1,msg,len);
  70.     while(TRUE)
  71.         DebugStr(buf);
  72. }
  73.  
  74. /*
  75.  * binary search the command table
  76.  */
  77. static int sfk_binsearch_cmd(char *look_me_up,int *insert_point)
  78. {
  79.     int high=sfk_cgl.sfk_cmd_table_size-1;
  80.     int cur=0;
  81.     int cval= 1;
  82.     int slen=strlen(look_me_up);
  83.  
  84.     while(cur<=high) {
  85.         cval=strncmp(look_me_up,sfk_cgl.sfk_cmd_table[cur].nm_text,slen);
  86.         if(cval<=0)
  87.             break;
  88.         cur++;
  89.     }
  90.     *insert_point=cur;
  91.     if((cval==0)&&
  92.         (cur<high)&&
  93.         (strncmp(look_me_up,sfk_cgl.sfk_cmd_table[cur+1].nm_text,slen)==0))
  94.             return sfk_BE_ambigous;
  95.     if(cval==0)
  96.         return sfk_BE_found;
  97.     return sfk_BE_not_found;
  98. }
  99.  
  100. /*
  101.  * allocate string space
  102.  */
  103. static char *sfk_alloc_string(int size)
  104. {
  105.     char *result=sfk_cgl.string_allocator;
  106.     sfk_cgl.string_allocator+=size;
  107.     return result;
  108. }
  109. /*
  110.  * add one command to the command table
  111.  */
  112. static void sfk_add_command(char *cname,int cnum,int cflags,char *help_text,char *xadd_default)
  113. {
  114.     int ins_point;
  115.     int i;
  116.     sfk_name_pt nm;
  117.     sfk_binsearch_cmd(cname,&ins_point);
  118.     sfk_cgl.sfk_cmd_table_size++;
  119.     for(i=(sfk_cgl.sfk_cmd_table_size-2);i>=ins_point;i--)
  120.         sfk_cgl.sfk_cmd_table[i+1]=sfk_cgl.sfk_cmd_table[i];
  121.     nm= &sfk_cgl.sfk_cmd_table[ins_point];
  122.     nm->nm_text=cname;
  123.     nm->nm_flags=cflags;
  124.     nm->nm_val_num=cnum;
  125.     nm->nm_help=help_text;
  126.     if(xadd_default==0)
  127.         nm->nm_default="";
  128.     else
  129.         nm->nm_default=xadd_default;
  130.     /*
  131.      * if this variable neads space, allocate string space for each port
  132.      */
  133.     if(((cflags&SFK_CF_IMMEDIATE)==0)&&
  134.        ((cflags&SFK_CF_ARG_MASK)==SFK_CF_TEXT))
  135.         for(i=0;i<sfk_NUM_PORTS;i++)
  136.             sfk_PN(i)->var_vals[cnum].x.nm_sval=
  137.                 sfk_alloc_string(sfk_STRING_SIZE);
  138. }
  139.  
  140. /*
  141.  * append a c string onto the end of a sfk_string
  142.  * don't overflow the output string
  143.  */
  144. void sfk_put_string(sfk_string_pt astr,char *add_on)
  145. {
  146.     int32 add_on_len=strlen(add_on)+1;
  147.     int32 space_available=astr->sfk_in_cnt-astr->sfk_out_cnt;
  148.     space_available=sfk_imax(0,sfk_imin(add_on_len,space_available));
  149.     if(space_available<=0)
  150.         return;
  151.     memcpy(astr->sfk_str+astr->sfk_out_cnt,add_on,space_available);
  152.     astr->sfk_out_cnt+=(space_available-1);
  153.     *(astr->sfk_str+astr->sfk_out_cnt)=0;
  154. }
  155.  
  156. /*
  157.  * append a string onto command output
  158.  */
  159. void sfk_cmd_out(sfk_iio_pt cmd,char *add_on)
  160. {
  161.     sfk_put_string(&cmd->uio->do_this.cknd.sfk_msg.omsg,add_on);
  162. }
  163.  
  164. /*
  165.  * report a command failure
  166.  */
  167. void sfk_parse_fail(sfk_iio_pt cmd,int fail_code,char *extra)
  168. {
  169. #define xDEBUG_FAILURES
  170. #ifdef DEBUG_FAILURES
  171.   {
  172.       char buf[256];
  173.       strcat(buf+1,"cfail ");
  174.       strcat(buf+1,"|");
  175.       strcat(buf+1,SFK_TEXT(41));
  176.       strcat(buf+1,"|");
  177.       strcat(buf+1,SFK_TEXT(fail_code));
  178.       strcat(buf+1,"|");
  179.       strcat(buf+1,((extra==0)?"":extra));
  180.       buf[0]=strlen(buf+1);
  181.     DebugStr((unsigned char *)buf);
  182.   }
  183. #endif
  184.     sfk_cmd_out(cmd,SFK_TEXT(41));
  185.     sfk_cmd_out(cmd,SFK_TEXT(fail_code));
  186.     if(extra!=0)
  187.         sfk_cmd_out(cmd,extra);
  188.     sfk_control_fail(cmd,0,fail_code);
  189. }
  190.  
  191. /*
  192.  * parse a an ascii string as a hex number
  193.  */
  194. static long parse_hex(sfk_iio_pt cmd,char *s)
  195. {
  196.     long result=0;
  197.     char *hex=sfk_map_text(65);
  198.     char *next;
  199.     char ch;
  200.     while((ch= *s++)!=0) {
  201.         if((next=strchr(hex,ch))==0)
  202.             sfk_parse_fail(cmd,TEXT_NUM(1),s);
  203.         result<<=4;
  204.         result+=(next-hex);
  205.     }
  206.     return result;
  207. }
  208.  
  209. /*
  210.  * parse a integer set command
  211.  */
  212. static int32 sfk_parse_integer(sfk_iio_pt cmd,char *cmd_word)
  213. {
  214.     register int32 result=0;
  215.     register char ch;
  216.     register char *instr=cmd_word;
  217.     while ((ch= *instr++)!=0) {
  218.         if(!isdigit(ch))
  219.             sfk_parse_fail(cmd,TEXT_NUM(1),cmd_word);
  220.         result*=10;
  221.         result+=ch-'0';
  222.     }
  223.     return result;
  224. }
  225.  
  226. /*
  227.  * parse a hex or decimal integer
  228.  */
  229. static int32 sfk_parse_hex_or_dec(sfk_iio_pt cmd,char *cmd_word)
  230. {
  231.     if((*cmd_word)!='$')
  232.         return sfk_parse_integer(cmd,cmd_word);
  233.     return parse_hex(cmd,cmd_word+1);
  234. }
  235.  
  236. /*
  237.  * setup debugging
  238.  */
  239. static void sfk_init_debugging(sfk_prt_pt p)
  240. {
  241. #ifdef DBO_ENABLED
  242.     if(p->dbo.dbo_guard2==dbo_GUARD2)
  243.         return;
  244.     dbo_fopen(&p->dbo);
  245.     p->dbo.just_kidding=(p->sfk_IVAR(debug_level)==0);
  246.     p->dbo.win_br.h=8*40;
  247.     switch(p->pnum) {
  248.       case sfk_PRINTER_PORT:
  249.         p->dbo.win_tl.v=30;
  250.         p->dbo.win_br.v=130;
  251.         break;
  252.       case sfk_MODEM_PORT:
  253.         p->dbo.win_tl.v=140;
  254.         p->dbo.win_br.v=240;
  255.         break;
  256.     }
  257.     dbo_fgoto(&p->dbo,0,0);
  258.     dbo_fclear(&p->dbo);
  259. #ifdef TEST_OUTPUT
  260.     {
  261.         int k;
  262.         int j;
  263.         for(k=0;k<10;k++)
  264.             for(j=' ';j<0x7f;j++)
  265.                 dbo_fputc(&p->dbo,j);
  266.     }
  267. #endif
  268. #endif
  269. }
  270.  
  271. /*
  272.  * reset port parameters to default values
  273.  */
  274. static void sfk_reset_port(sfk_iio_pt cmd,sfk_prt_pt p)
  275. {
  276.   int i;
  277.   sfk_name_pt nm;
  278.   p->sfk_IVAR(port)=p->pnum;
  279.   for(i=0;i<sfk_max_cmd_num;i++) {
  280.       nm= &sfk_cgl.sfk_cmd_table[i];
  281.       p->var_vals[nm->nm_val_num].changed=TRUE;
  282.     switch(nm->nm_flags&SFK_CF_ARG_MASK) {
  283.         case SFK_CF_NO_ARG:
  284.            break;
  285.         case SFK_CF_BOOL:
  286.         case SFK_CF_INT:
  287.            p->var_vals[nm->nm_val_num].x.nm_ival=sfk_parse_hex_or_dec(cmd,nm->nm_default);
  288.           break;
  289.         case SFK_CF_TEXT:
  290.           strcpy(p->var_vals[nm->nm_val_num].x.nm_sval,nm->nm_default);
  291.           break;
  292.         }
  293.   }
  294.   sfk_init_debugging(p);
  295. }
  296.  
  297. /*
  298.  * map a port number to a name
  299.  * drivers can't have static data point to other static data
  300.  * so this can't be a simple array access
  301.  */
  302. static char *name_port(int n)
  303. {
  304.     switch(n) {
  305.     case sfk_PRINTER_PORT:
  306.         return SFK_TEXT(42);
  307.     case sfk_MODEM_PORT:
  308.         return SFK_TEXT(43);
  309.     default:
  310.         return SFK_TEXT(45);
  311.     }
  312. }
  313.  
  314. /*
  315.  * reset settings of all ports
  316.  */
  317. static void sfk_reset_ports(sfk_iio_pt cmd)
  318. {
  319.   int i;
  320.   for(i=0;i<sfk_NUM_PORTS;i++) {
  321.     sfk_prt_pt p=sfk_PN(i);
  322.     p->pnum=i;
  323.     p->port_name=name_port(i);
  324.     sfk_reset_port(cmd,p);
  325.   }
  326. }
  327.  
  328. /*
  329.  * define the command procedures
  330.  */
  331. #define SFK_CMD(xx_cmd_name,xx_cmd_arg_type,xx_cmd_help,xx_default) \
  332.     void sfk_cmd_proc_##xx_cmd_name(void);
  333. #include "sfk_core_command.h"
  334. #undef SFK_CMD
  335.  
  336. /*
  337.  * setup string space allocator
  338.  */
  339. static void sfk_init_string_allocator()
  340. {
  341.     sfk_cgl.string_allocator=sfk_cgl.string_space;
  342. }
  343.  
  344. /*
  345.  * allocate queue memory now in case we are under finder
  346.  */
  347. static void sfk_alloc_mem(sfk_iio_pt cmd)
  348. {
  349.   int i;
  350.   for(i=0;i<sfk_NUM_PORTS;i++) {
  351.     sfk_prt_pt p=sfk_PN(i);
  352.     sfk_soft_tnc_install(cmd,p);
  353.     sfk_allocate_queue_memory(cmd,p);
  354.     sfk_allocate_soft_tnc_memory(cmd,p);
  355.   }
  356. }
  357.  
  358. /*
  359.  * map a failure code to it's text
  360.  */
  361. char *sfk_map_text(int text_code)
  362. {
  363.     return (char *)
  364.       (sfk_gl.dt_text.tptr+(*(sfk_gl.dt_text.tstrs+text_code)));
  365. }
  366.  
  367. /*
  368.  * read in in map text
  369.  */
  370. static void init_map_text(sfk_iio_pt cmd)
  371. {
  372.     if(!sfk_dt_load(SFK_TEXT_RESID,&sfk_gl.dt_text,sfk_malloc,sfk_free))
  373.         sfk_parse_fail(cmd,TEXT_NUM(64),0);
  374. }
  375.  
  376. /*
  377.  * split an input string
  378.  */
  379. static int split(char **dst,int limit,char *in)
  380. {
  381.     int result=0;
  382.     while(result<limit) {
  383.         *dst++= in;
  384.         result++;
  385.         if((in=strchr(in,'|'))==0)
  386.             break;
  387.         *in++=0;
  388.     }
  389.     return result;
  390. }
  391.  
  392. /*
  393.  * add the command table
  394.  */
  395. static void add_commands(sfk_iio_pt cmd)
  396. {
  397.     dyn_text dt;                /*dt text*/
  398.     int i;
  399.     if(!sfk_dt_load(SFK_COMMAND_RESID,&dt,sfk_malloc,sfk_free))
  400.         sfk_parse_fail(cmd,TEXT_NUM(64),0);
  401.     for(i=1;i<=dt.nstrs;i++){
  402.         char *args[6];
  403.         long nm_flags;
  404.         if(split(args,6,(char *)(dt.tptr+(*(dt.tstrs+i))))!=4)
  405.             sfk_parse_fail(cmd,TEXT_NUM(64),0);
  406.         nm_flags=parse_hex(cmd,args[3]);
  407.         sfk_add_command(args[0],i-1,nm_flags,args[1],args[2]);
  408.     }
  409.     sfk_dt_free(&dt);
  410. }
  411.  
  412. /*
  413.  * update version string
  414.  */
  415. static void upd_version(void)
  416. {
  417.     Handle vers=GetResource('vers',1);
  418.     int len;
  419.     char *vers_str;
  420.     if(vers==0) {    //hmm, can't get the real version
  421.         strcpy(sfk_gl.vers,__DATE__);
  422.         return;
  423.     }
  424.     vers_str= (*vers)+6;
  425.       len= (*vers_str++)&0x0F;
  426.       memcpy(sfk_gl.vers,vers_str,len);
  427.       sfk_gl.vers[len]=0;
  428. }
  429.  
  430. /*
  431.  * add all the commands to the command table
  432.  * Note: This is done as code as think c code resources/drivers
  433.  * can't have static initializers that point to addresses ie
  434.  */
  435. void sfk_init_commands(sfk_iio_pt cmd)
  436. {
  437.     init_map_text(cmd);
  438.     sfk_init_string_allocator();
  439. #define xCOMMANDS_FROM_H_FILE_NOT_RESOURCE
  440. #ifdef COMMANDS_FROM_H_FILE_NOT_RESOURCE
  441. #define SFK_CMD(xx_cmd_name,xx_cmd_arg_type,xx_cmd_help,xx_default) \
  442.     sfk_add_command( #xx_cmd_name,sfk_cval_##xx_cmd_name,xx_cmd_arg_type,xx_cmd_help,xx_default);
  443. #include "sfk_core_command.h"
  444. #undef SFK_CMD
  445. #else
  446.     add_commands(cmd);
  447. #endif
  448.     sfk_reset_ports(cmd);
  449.     sfk_patch_in_global_data();
  450.     upd_version();
  451.     sfk_alloc_mem(cmd);
  452. }
  453.  
  454. /*
  455.  * get a new current character
  456.  */
  457. static void sfk_nextch(sfk_iio_pt cmd)
  458. {
  459.   if(cmd->pqx.eof)
  460.       sfk_parse_fail(cmd,TEXT_NUM(2),0);
  461.   if(cmd->uio->do_this.cknd.sfk_msg.imsg.sfk_out_cnt>=cmd->uio->do_this.cknd.sfk_msg.imsg.sfk_in_cnt)
  462.     cmd->pqx.eof=TRUE;
  463.   if(cmd->pqx.eof) return;
  464.   cmd->pqx.ch= *cmd->uio->do_this.cknd.sfk_msg.imsg.sfk_str++;
  465.   cmd->uio->do_this.cknd.sfk_msg.imsg.sfk_out_cnt++;
  466. }
  467.  
  468. /*
  469.  * is the current character white space?
  470.  */
  471. static int sfk_is_white_space(sfk_iio_pt cmd)
  472. {
  473.     return ((cmd->pqx.ch==' ')||(cmd->pqx.ch=='\t'));
  474. }
  475.  
  476. /*
  477.  * is the current character end of line
  478.  */
  479. static int sfk_is_eol(sfk_iio_pt cmd)
  480. {
  481.     return ((cmd->pqx.ch=='\n') || (cmd->pqx.ch==FAKE_EOL_CH));
  482. }
  483.  
  484. /*
  485.  * skip white space
  486.  */
  487. static void sfk_skip_white_space(sfk_iio_pt cmd)
  488. {
  489.   while(!cmd->pqx.eof) {
  490.     if(!sfk_is_white_space(cmd))
  491.       break;
  492.     sfk_nextch(cmd);
  493.   }
  494. }
  495.  
  496. /*
  497.  * say if a character is part of a token
  498.  */
  499. static int sfk_token_ch(char ch)
  500. {
  501.     return ((!(ch==FAKE_EOL_CH))&&(ch>' ')&&(ch<0x7f));
  502. }
  503.  
  504. /*
  505.  * parse one word from the input stream
  506.  */
  507. static void sfk_parse_word(sfk_iio_pt cmd,char *aword)
  508. {
  509.     int word_len=0;
  510.     char ch;
  511.     if(cmd->pqx.eof)
  512.         sfk_parse_fail(cmd,TEXT_NUM(3),0);
  513.     do {
  514.         if(!sfk_token_ch(cmd->pqx.ch))
  515.             sfk_parse_fail(cmd,TEXT_NUM(4),0);
  516.         if(word_len>=(sfk_MAX_TOKEN-1))
  517.             sfk_parse_fail(cmd,TEXT_NUM(5),0);
  518.         *aword++=cmd->pqx.ch;
  519.          sfk_nextch(cmd);
  520.     } while(sfk_token_ch(cmd->pqx.ch)&&(!cmd->pqx.eof));
  521.     *aword=0;
  522.     if(cmd->pqx.eof||sfk_is_white_space(cmd)||sfk_is_eol(cmd))
  523.         return;
  524.     sfk_parse_fail(cmd,TEXT_NUM(6),0);
  525. }
  526.  
  527. /*
  528.  * parse end of input line
  529.  */
  530. static void sfk_parse_eol(sfk_iio_pt cmd)
  531. {
  532.   sfk_skip_white_space(cmd);
  533.   if(cmd->pqx.eof)
  534.     return;
  535.   if(!sfk_is_eol(cmd))
  536.       sfk_parse_fail(cmd,TEXT_NUM(7),0);
  537.   sfk_nextch(cmd);    /*consume the end of line character*/
  538. }
  539.  
  540. /*
  541.  * case insensitive compare of a string vs a keyword
  542.  * if no characters in string then do match
  543.  */
  544. static int strmatch(const char *astr,const char *key_word)
  545. {
  546.     register char  ach;
  547.     while((ach=(*astr++))!=0) {
  548.         if(isupper(ach))
  549.             ach=tolower(ach);
  550.         if (ach == (*key_word++))
  551.             continue;
  552.         return FALSE;
  553.     }
  554.     return true;
  555. }
  556.  
  557. /*
  558.  * case insensitive compare of a string vs a keyword
  559.  * if no characters in string then don't match
  560.  */
  561. static int strmatch_some(const char *astr,const char *key_word)
  562. {
  563.     if((*astr)==0)
  564.         return FALSE;
  565.     return strmatch(astr,key_word);
  566. }
  567. /*
  568.  * parse a boolean set command
  569.  */
  570. static int sfk_parse_bool(sfk_iio_pt cmd,char *cmd_word)
  571. {
  572.     int wlen=strlen(cmd_word);
  573.     if(strmatch_some(cmd_word,SFK_TEXT(46)))
  574.         return TRUE;
  575.     if(strmatch_some(cmd_word,SFK_TEXT(47)))
  576.         return FALSE;
  577.     sfk_parse_fail(cmd,TEXT_NUM(8),cmd_word);
  578.     SFK_NEVER_RETURN(0);
  579. }
  580.  
  581. /*
  582.  * return command table entry to dump to resource fork
  583.  * used in test program
  584.  */
  585. int sfk_cmd_dump(int idx,char **nm_text,char **nm_help,
  586.     char **nm_default,long *nm_flags,short *nm_val_num)
  587. {
  588.     if(idx>=sfk_cgl.sfk_cmd_table_size)
  589.         return FALSE;
  590.     *nm_text=sfk_cgl.sfk_cmd_table[idx].nm_text;
  591.     *nm_help=sfk_cgl.sfk_cmd_table[idx].nm_help;
  592.     *nm_default=sfk_cgl.sfk_cmd_table[idx].nm_default;
  593.     *nm_flags=sfk_cgl.sfk_cmd_table[idx].nm_flags;
  594.     *nm_val_num=sfk_cgl.sfk_cmd_table[idx].nm_val_num;
  595.     return TRUE;
  596. }
  597.  
  598. /*
  599.  * give help command
  600.  */
  601. static void sfk_help(sfk_iio_pt cmd,char *on_what)
  602. {
  603.     int high=sfk_cgl.sfk_cmd_table_size-1;
  604.     int cur=0;
  605.     SFK_UNUSED_ARG(on_what);
  606.     while(cur<=high) {
  607.         sfk_cmd_out(cmd,sfk_cgl.sfk_cmd_table[cur].nm_text);
  608.         sfk_cmd_out(cmd,SFK_TEXT(48));
  609.         sfk_cmd_out(cmd,sfk_cgl.sfk_cmd_table[cur].nm_help);
  610.         sfk_cmd_out(cmd,SFK_TEXT(58));
  611.         cur++;
  612.     }
  613. }
  614.  
  615. /*
  616.  * convert an unsigned number to text
  617.  */
  618. static char *textify_unisgned_number(char *out,long anum)
  619. {
  620.     long remainder=anum%10;
  621.     anum/=10;
  622.     if(anum!=0)
  623.         out=textify_unisgned_number(out,anum);
  624.     *out++ ='0'+remainder;
  625.     return out;
  626. }
  627.  
  628. /*
  629.  * convert a number to text
  630.  */
  631. static void textify_number(char *out,long anum)
  632. {
  633.     if(anum<0) {
  634.         *out++='-';
  635.         anum= -anum;
  636.     }
  637.     *textify_unisgned_number(out,anum)=0;
  638. }
  639.  
  640. /*
  641.  * ask a command to display itself
  642.  */
  643. static void display_cmd(sfk_iio_pt cmd,int cmd_num)
  644. {
  645.     switch(cmd_num) {
  646.     case sfk_CMD_NUM(port):
  647.         sfk_cmd_out(cmd,cmd->pqx.p->port_name);
  648.         break;
  649.     case sfk_CMD_NUM(display):
  650.     case sfk_CMD_NUM(help):
  651.     default:
  652.         sfk_cmd_out(cmd,SFK_TEXT(49));
  653.     }
  654. }
  655.  
  656. /*
  657.  * display as text the value of a variable
  658.  */
  659. static void sfk_display_nm(sfk_iio_pt cmd,sfk_name_pt cur_nm)
  660. {
  661.   sfk_cmd_out(cmd,cur_nm->nm_text);
  662.   if(cur_nm->nm_flags&SFK_CF_RO)
  663.       sfk_cmd_out(cmd,SFK_TEXT(50));
  664.   sfk_cmd_out(cmd,SFK_TEXT(51));
  665.   switch(cur_nm->nm_flags&SFK_CF_ARG_MASK) {
  666.     case SFK_CF_NO_ARG:
  667.       sfk_parse_fail(cmd,TEXT_NUM(9),cur_nm->nm_text);
  668.        break;
  669.     case SFK_CF_BOOL:
  670.        if(sfk_PN(cmd->pqx.p->pnum)->var_vals[cur_nm->nm_val_num].x.nm_ival)
  671.            sfk_cmd_out(cmd,SFK_TEXT(46));
  672.        else
  673.            sfk_cmd_out(cmd,SFK_TEXT(47));
  674.       break;
  675.     case SFK_CF_INT:
  676.       {
  677.           char buf[60];
  678.           textify_number(buf,sfk_PN(cmd->pqx.p->pnum)->var_vals[cur_nm->nm_val_num].x.nm_ival);
  679.           sfk_cmd_out(cmd,buf);
  680.       }
  681.       break;
  682.     case SFK_CF_TEXT:
  683.       if((cur_nm->nm_flags&SFK_CF_IMMEDIATE)!=0)
  684.         display_cmd(cmd,cur_nm->nm_val_num);
  685.        else
  686.            sfk_cmd_out(cmd,sfk_PN(cmd->pqx.p->pnum)->var_vals[cur_nm->nm_val_num].x.nm_sval);
  687.       break;
  688.     }
  689.   sfk_cmd_out(cmd,SFK_TEXT(58));
  690. }
  691.  
  692. /*
  693.  * display the value of variables
  694.  */
  695. static void sfk_display(sfk_iio_pt cmd,char *vnames)
  696. {
  697.   int cmd_num=0;
  698.   sfk_name_pt cur_nm;
  699.   if(vnames[0]!=0)
  700.   switch(sfk_binsearch_cmd(vnames,&cmd_num)) {
  701.      case sfk_BE_not_found:
  702.       sfk_parse_fail(cmd,TEXT_NUM(10),vnames);
  703.       break;        //never executed
  704.     case sfk_BE_ambigous:
  705.       break;
  706.     case sfk_BE_found:
  707.       break;
  708.   }
  709.   cur_nm= &sfk_cgl.sfk_cmd_table[cmd_num];
  710.   while(strmatch(vnames,cur_nm->nm_text)&&
  711.       (cur_nm < &sfk_cgl.sfk_cmd_table[sfk_cgl.sfk_cmd_table_size]))
  712.       sfk_display_nm(cmd,cur_nm++);
  713. }
  714.  
  715. /*
  716.  * validate and select the requested port
  717.  */
  718. static void sfk_set_port(sfk_iio_pt cmd,int portno)
  719. {
  720.   if(portno== (-1))        /*-1 means leave port set as it is*/
  721.       portno=cmd->pqx.p->pnum;
  722.   if(portno>=sfk_NUM_PORTS)
  723.     sfk_parse_fail(cmd,TEXT_NUM(11),0);
  724.   cmd->pqx.p=sfk_PN(portno);
  725. }
  726.  
  727. /*
  728.  * fail if a port is not selected
  729.  */
  730. static void sfk_need_port(sfk_iio_pt cmd)
  731. {
  732.   if((cmd->pqx.p == 0)||(cmd->pqx.p->pnum<0)||(cmd->pqx.p->pnum>=sfk_NUM_PORTS))
  733.     sfk_parse_fail(cmd,TEXT_NUM(12),0);
  734. }
  735.  
  736. /*
  737.  * parse the name of a port
  738.  */
  739. static long parse_port(sfk_iio_pt cmd,char *arg_word)
  740. {
  741.   int i;
  742.   if(isdigit(*arg_word))
  743.     return sfk_parse_hex_or_dec(cmd,arg_word);
  744.   for(i=0;i<sfk_NUM_PORTS;i++) {
  745.     sfk_prt_pt p=sfk_PN(i);
  746.     if(strmatch_some(arg_word,p->port_name))
  747.         return p->pnum;
  748.   }
  749.   sfk_parse_fail(cmd,TEXT_NUM(13),arg_word);
  750.   SFK_NEVER_RETURN(0);
  751. }
  752.  
  753. /*
  754.  * set a non immediate value
  755.  */
  756. static void perform_immediate(sfk_iio_pt cmd,char *arg_word,int32 ival,sfk_name_pt cur_nm)
  757. {
  758.     switch(cur_nm->nm_val_num) {
  759.     case sfk_CMD_NUM(help):
  760.         sfk_help(cmd,arg_word);
  761.         break;
  762.     case sfk_CMD_NUM(display):
  763.         sfk_display(cmd,arg_word);
  764.         break;
  765.     case sfk_CMD_NUM(port):
  766.         {
  767.           int nval=parse_port(cmd,arg_word);
  768.           sfk_set_port(cmd,nval);
  769.         }
  770.         break;
  771.     case sfk_CMD_NUM(debug_level):
  772.         sfk_need_port(cmd);
  773.         cmd->pqx.p->sfk_IVAR(debug_level)=ival;
  774. #ifdef DBO_ENABLED
  775.         cmd->pqx.p->dbo.just_kidding=(ival==0);
  776.         dbo_fclear(&cmd->pqx.p->dbo);
  777. #endif
  778.         break;
  779.     case sfk_CMD_NUM(online):
  780.         sfk_need_port(cmd);
  781.         sfk_change_online(cmd,ival);
  782.         break;
  783.     case sfk_CMD_NUM(kiss):
  784.         sfk_need_port(cmd);
  785.         sfk_change_kiss(cmd,ival);
  786.         break;
  787.     case sfk_CMD_NUM(soft_tnc):
  788.         sfk_need_port(cmd);
  789.         sfk_change_soft_tnc(cmd,ival);
  790.         break;
  791.     case sfk_CMD_NUM(shutdown):
  792.         sfk_shutdown(cmd);
  793.         break;
  794.     default:     
  795.         sfk_parse_fail(cmd,TEXT_NUM(14),cur_nm->nm_text);
  796.     }
  797. }
  798.  
  799. /*
  800.  * set a non immediate value
  801.  */
  802. static void set_non_immediate(sfk_iio_pt cmd,char *arg_word,int32 ival,sfk_name_pt cur_nm)
  803. {
  804.   sfk_need_port(cmd);
  805.   if(cur_nm->nm_flags&SFK_CF_RO)
  806.     sfk_parse_fail(cmd,TEXT_NUM(15),cur_nm->nm_text);
  807.   if(cmd->pqx.p->sfk_IVAR(online)!=0)
  808.     sfk_parse_fail(cmd,TEXT_NUM(16),cur_nm->nm_text);
  809.   sfk_PN(cmd->pqx.p->pnum)->var_vals[cur_nm->nm_val_num].changed=TRUE;
  810.   switch(cur_nm->nm_flags&SFK_CF_ARG_MASK) {
  811.     case SFK_CF_NO_ARG:
  812.       if(arg_word[0]!=0)
  813.         sfk_parse_fail(cmd,TEXT_NUM(17),arg_word);
  814.       break;
  815.     case SFK_CF_BOOL:
  816.        sfk_PN(cmd->pqx.p->pnum)->var_vals[cur_nm->nm_val_num].x.nm_ival=ival;
  817.       break;
  818.     case SFK_CF_INT:
  819.        sfk_PN(cmd->pqx.p->pnum)->var_vals[cur_nm->nm_val_num].x.nm_ival=ival;
  820.       break;
  821.     case SFK_CF_TEXT:
  822.       if(strlen(arg_word)>=sfk_STRING_SIZE)
  823.           sfk_parse_fail(cmd,TEXT_NUM(18),arg_word);
  824.       strcpy(sfk_PN(cmd->pqx.p->pnum)->var_vals[cur_nm->nm_val_num].x.nm_sval,arg_word);
  825.       break;
  826.     }
  827.   }
  828.  
  829. /*
  830.  * parse and execute one line of input from the command object
  831.  */
  832. static void sfk_parse_1_command(sfk_iio_pt cmd)
  833. {
  834.   char cmd_word[sfk_MAX_TOKEN];
  835.   char arg_word[sfk_MAX_TOKEN];
  836.   sfk_name_pt cur_nm;
  837.   int cmd_num;
  838.   int32 ival=0;
  839.  
  840.   sfk_skip_white_space(cmd);
  841.   sfk_parse_word(cmd,cmd_word);
  842.   sfk_skip_white_space(cmd);
  843.   switch(sfk_binsearch_cmd(cmd_word,&cmd_num)) {
  844.      case sfk_BE_not_found:
  845.       sfk_parse_fail(cmd,TEXT_NUM(19),cmd_word);
  846.       break;        //never gets executed
  847.     case sfk_BE_ambigous:
  848.       sfk_parse_fail(cmd,TEXT_NUM(20),cmd_word);
  849.       break;        //never gets executed
  850.     case sfk_BE_found:
  851.       break;
  852.   }
  853.   cur_nm= &sfk_cgl.sfk_cmd_table[cmd_num];
  854.   arg_word[0]=0;
  855.   if(!(cmd->pqx.eof || sfk_is_eol(cmd)))
  856.       sfk_parse_word(cmd,arg_word);
  857.   else if((cur_nm->nm_flags&SFK_CF_IMMEDIATE)==0) {
  858.     //if no argument pretend it is a display command
  859.       sfk_display_nm(cmd,cur_nm);
  860.       return;
  861.   }
  862.   switch(cur_nm->nm_flags&SFK_CF_ARG_MASK) {
  863.     case SFK_CF_NO_ARG:
  864.       if(arg_word[0]!=0)
  865.         sfk_parse_fail(cmd,TEXT_NUM(21),arg_word);
  866.       break;
  867.     case SFK_CF_BOOL:
  868.       ival=sfk_parse_bool(cmd,arg_word);
  869.       break;
  870.     case SFK_CF_INT:
  871.       ival=sfk_parse_hex_or_dec(cmd,arg_word);
  872.       break;
  873.     case SFK_CF_TEXT:
  874.       break;
  875.    }
  876.   if((cur_nm->nm_flags&SFK_CF_IMMEDIATE)==0)
  877.     set_non_immediate(cmd,arg_word,ival,cur_nm);
  878.   else
  879.     perform_immediate(cmd,arg_word,ival,cur_nm);
  880.   sfk_parse_eol(cmd);
  881. }
  882.  
  883. /*
  884.  * parse and execute the passed commands
  885.  */
  886. void sfk_parse_command(sfk_iio_pt cmd)
  887. {
  888.   cmd->pqx.eof=FALSE;
  889.   cmd->pqx.p=0;
  890.   sfk_set_port(cmd,cmd->uio->do_this.cknd.sfk_msg.portno);
  891.   sfk_nextch(cmd);
  892.   while(!cmd->pqx.eof) {        /*do each line till eof or error*/
  893.       sfk_parse_1_command(cmd);
  894.       if(cmd->pqx.p!=0)            /*update selected port even if error later*/
  895.           cmd->uio->do_this.cknd.sfk_msg.portno=cmd->pqx.p->pnum;
  896.   }
  897. }
  898.